package com.qi.pay.demo.util;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

/**
 * http请求
 *
 */
public class HttpUtils {
	
	/** 连接超时时间 */
	private final static int CONN_TIMEOUT = 5000;
	/** 请求超时时间 */
	private final static int SO_TIMEOUT = 10000;
	
	public static void main(String[] args) {
		try {
			System.out.println(HttpUtils.doGet("http://www.baidu.com", null, null, null));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Get请求
	 * @param url
	 * @param headerMap
	 * @param connTimeOut, 为null,表示使用默认值5000
	 * @param soTimeOut, 为null,表示使用默认值10000
	 * @return
	 * @throws IOException
	 */
	public static HttpResponse doGet(String url, Map<String, String> headerMap, Integer connTimeOut, Integer soTimeOut) throws IOException {
		HttpResponse httpResponse = new HttpResponse();
		HttpClient httpClient = new HttpClient();
		httpClient.getHttpConnectionManager().getParams().setConnectionTimeout((connTimeOut == null) ? HttpUtils.CONN_TIMEOUT : connTimeOut); 
		
		// 模拟 Get 提交 可以正常使用
		GetMethod getMethod = new GetMethod(url);
		getMethod.setRequestHeader("Connection", "close");
		getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
		getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, (soTimeOut == null) ? HttpUtils.SO_TIMEOUT : soTimeOut);  
		getMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");

		// 设置 请求头信息
		if(headerMap != null && headerMap.size() > 0){
			Set<Map.Entry<String, String>> set = headerMap.entrySet();
	        for (Iterator<Map.Entry<String, String>> it = set.iterator(); it.hasNext();) {
	            Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next();
	            getMethod.setRequestHeader(entry.getKey(), entry.getValue());
	        }
		}
		try {
			int statusCode = httpClient.executeMethod(getMethod);
			httpResponse.setStatusCode(statusCode);
			if (statusCode != HttpStatus.SC_OK) {
				httpResponse.setResponseBody(new String(getMethod.getResponseBodyAsString()));
				
				Map<String, String> responseHeaderMap = new HashMap<>();
				Header[] responseHeaders = getMethod.getResponseHeaders();
				for(Header header : responseHeaders) {
					responseHeaderMap.put(header.getName(), header.getValue());
				}
				httpResponse.setHeaderMap(responseHeaderMap);
			} else {
				httpResponse.setResponseBody("");
			}
		} catch (HttpException e) {
			getMethod.abort();
			e.printStackTrace();
			throw e;
		} catch (IOException e) {
			getMethod.abort();
			e.printStackTrace();
			throw e;
		} finally {
			getMethod.releaseConnection();
		}
		return httpResponse;
	}
	
	/**
	 * Post请求
	 * @param url
	 * @param requestBody
	 * @param headerMap
	 * @param connTimeOut, 为null,表示使用默认值5000
	 * @param soTimeOut, 为null,表示使用默认值10000
	 * @return
	 * @throws IOException
	 */
	@SuppressWarnings("deprecation")
	public static HttpResponse doPost(String url, String requestBody, Map<String, String> headerMap, Integer connTimeOut, Integer soTimeOut) throws IOException {
		HttpResponse httpResponse = new HttpResponse();
		HttpClient httpClient = new HttpClient();
		httpClient.getHttpConnectionManager().getParams().setConnectionTimeout((connTimeOut == null) ? HttpUtils.CONN_TIMEOUT : connTimeOut); // 连接超时
		
		PostMethod postMethod = new PostMethod(url);
		postMethod.setRequestHeader("Connection", "close");
		if(requestBody != null && requestBody.length() > 0){
			postMethod.setRequestBody(requestBody);
		}
		postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
		postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, (soTimeOut == null) ? HttpUtils.SO_TIMEOUT : soTimeOut); // post请求超时
		postMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
		postMethod.addRequestHeader("Content-Type", "application/json");
		//设置 http请求头信息
		if(headerMap != null && headerMap.size() > 0){
			Set<Map.Entry<String, String>> set = headerMap.entrySet();
	        for (Iterator<Map.Entry<String, String>> it = set.iterator(); it.hasNext();) {
	            Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next();
	            postMethod.setRequestHeader(entry.getKey(), entry.getValue());
	        }
		}
		try {
			int statusCode = httpClient.executeMethod(postMethod);
			httpResponse.setStatusCode(statusCode);
			if (statusCode == HttpStatus.SC_OK) {
				httpResponse.setResponseBody(new String(postMethod.getResponseBodyAsString()));
				
				Map<String, String> responseHeaderMap = new HashMap<>();
				Header[] responseHeaders = postMethod.getResponseHeaders();
				for(Header header : responseHeaders) {
					responseHeaderMap.put(header.getName(), header.getValue());
				}
				httpResponse.setHeaderMap(responseHeaderMap);
			} else {
				httpResponse.setResponseBody("");
			}
		} catch (HttpException e) {
			postMethod.abort();
			e.printStackTrace();
			throw e;
		} catch (IOException e) {
			postMethod.abort();
			e.printStackTrace();
			throw e;
		} finally {
			postMethod.releaseConnection();
		}
		return httpResponse;
	}
	
	public static class HttpResponse{
		
		private String responseBody;
		private int statusCode;
		private Map<String, String> headerMap;
		public String getResponseBody() {
			return responseBody;
		}
		public void setResponseBody(String responseBody) {
			this.responseBody = responseBody;
		}
		public int getStatusCode() {
			return statusCode;
		}
		public void setStatusCode(int statusCode) {
			this.statusCode = statusCode;
		}
		public Map<String, String> getHeaderMap() {
			return headerMap;
		}
		public void setHeaderMap(Map<String, String> headerMap) {
			this.headerMap = headerMap;
		}
		
	}
}
